<?php

namespace common\util;

use common\enums\ResponseCode;
use common\util\assert\AssertUtil;

class EncryptionUtil
{
    /**
     * @var string
     */
    private string $key = 'abcdefghijklmnopqrstuvwxyz';

    /**
     * @var string
     */
    private string $encryptionLock = '';


    public function __construct()
    {
        $this->encryptionLock = config('yijiantianOA.RAND_KEY');
        $this->setRandKey($this->encryptionLock);
    }

    /**
     * @param $string
     */
    public function setRandKey($string)
    {
        $this->encryptionLock = $string;
        if (strlen($this->encryptionLock) != 26) {
            $this->encryptionLock = $this->key;
        }
    }


    /**
     * base64加密
     *
     * @param string $str
     * @return array|string
     */
    public function base64Encode(string $str): array|string
    {
        AssertUtil::notEmpty($str, ResponseCode::THE_ENCRYPTED_OBJECT_CANNOT_BE_EMPTY());
        return str_replace(
            ['+', '/', '='],
            ['!', '.', ':'],
            base64_encode($str)
        );
    }

    /**
     * base64解密
     *
     * @param string $str
     * @return bool|string
     */
    public function base64Decode(string $str): bool|string
    {
        AssertUtil::notEmpty($str, ResponseCode::THE_ENCRYPTED_OBJECT_CANNOT_BE_EMPTY());
        return base64_decode(
            str_replace(
                ['!', '.', ':'],
                ['+', '/', '='],
                $str
            )
        );
    }

    /**
     * 加密字符串
     *
     * @param string $string
     * @param string $lx
     * @return string
     */
    public function encrypt(string $string, $lx = ''): string
    {
        $encryptionString = $this->getEncryptionString($lx);
        $string = $this->base64Encode($string);
        return $this->encrypts($string, $encryptionString);
    }

    /**
     * 解密字符串
     *
     * @param string $string
     * @param string $lx
     * @return bool|string
     */
    public function decrypt(string $string, $lx = ''): bool|string
    {
        $encryptionString = $this->getEncryptionString($lx);
        $string = $this->decrypts($string, $encryptionString);
        return $this->base64decode($string);
    }

    /**
     * @param string $string
     * @param string $encryptionString
     * @return string
     */
    public function encrypts(string $string, string $encryptionString): string
    {
        if ($encryptionString == '') {
            $encryptionString = $this->encryptionLock;
        }

        $newString = '';
        if (empty($string)) {
            return $newString;
        }

        $len = strlen($string);
        $t = rand(1, 14);
        if ($t == 10) {
            $t++;
        }
        for ($i = 0; $i < $len; $i++) {
            $newString .= '0';
            $sta = substr($string, $i, 1);
            $orStr = '' . ord($sta) . '';
            $ile = strlen($orStr);
            for ($j = 0; $j < $ile; $j++) {
                $oi = (int)substr($orStr, $j, 1) + $t;
                $newString .= substr($encryptionString, $oi, 1);
            }
        }
        if ($newString != '') {
            $newString = substr($newString, 1);
            $newString .= '0' . $t . '';
        }
        return $newString;
    }

    /**
     * @param string $string
     * @param string $encryptionString
     * @return string
     */
    public function decrypts(string $string, string $encryptionString = ''): string
    {
        $newString = '';
        if (empty($string)) {
            return $newString;
        }
        if ($encryptionString == '') {
            $encryptionString = $this->encryptionLock;
        }

        $a = [];
        for ($i = 0; $i < strlen($encryptionString); $i++) {
            $a[substr($encryptionString, $i, 1)] = '' . $i . '';
        }

        $na = explode('0', $string);
        $len = count($na);
        $r = (int)$na[$len - 1];
        for ($i = 0; $i < $len - 1; $i++) {
            $st = $na[$i];
            $sl = strlen($st);
            $sa = '';
            for ($j = 0; $j < $sl; $j++) {
                $ha = substr($st, $j, 1);
                if (isset($a[$ha])) $ha = $a[$ha] - $r;
                $sa .= $ha;
            }
            $sa = (int)$sa;
            $newString .= chr($sa);
        }

        return $newString;
    }


    /**
     * 获取加密字符串
     *
     * @param $lx
     * @return string
     */
    private function getEncryptionString($lx): string
    {
        $string = '';
        if (is_numeric($lx) && $lx > 0) {
            $string = $this->getRandomString($lx);
        } else if (is_string($lx)) {
            if (strlen($lx) == 26) {
                $string = $lx;
            }
        }

        return $string;
    }

    /**
     * 获取随机字符串
     *
     * @param int $oi
     * @param string $string
     * @return string
     */
    private function getRandomString(int $oi, string $string = ''): string
    {
        $string = $string == '' ? $this->key : $string;
        $oi = $oi > 100 ? 100 : $oi;

        $stringLength = strlen($string);
        $cutLength = 6;

        $string1 = substr($string, 0, $cutLength);
        $string2 = substr($string, $cutLength, $cutLength);
        $string3 = substr($string, $cutLength * 2, $stringLength - $cutLength * 2);

        $randomString = $string3 . $string2 . $string1;

        if ($oi > 0) {
            $randomString = $this->getRandomString($oi - 1, $randomString);
        }

        return $randomString;
    }


}